🔀 Strutture di Controllo in Python

Condizioni, cicli e controllo del flusso del programma

Introduzione: Controllare il flusso del programma

Finora abbiamo scritto programmi che eseguono istruzioni in modo sequenziale, dall'alto verso il basso. Tuttavia, la vera potenza della programmazione emerge quando possiamo far prendere decisioni al programma e far ripetere operazioni. Le strutture di controllo ci permettono di controllare il flusso di esecuzione del codice, creando programmi dinamici e intelligenti.

📘 Le tre strutture fondamentali

Ogni programma può essere costruito usando solo tre tipi di strutture di controllo:

  • Sequenza: eseguire istruzioni una dopo l'altra (quello che già conosci)
  • Selezione: scegliere quale codice eseguire in base a condizioni (if, elif, else)
  • Iterazione: ripetere blocchi di codice (while, for)

1. Operatori di confronto

Prima di esplorare le strutture condizionali, dobbiamo capire come Python valuta le condizioni. Gli operatori di confronto confrontano due valori e restituiscono un valore booleano (True o False).

Operatore Significato Esempio Risultato
== Uguale a 5 == 5 True
!= Diverso da 5 != 3 True
> Maggiore di 10 > 8 True
< Minore di 3 < 7 True
>= Maggiore o uguale a 5 >= 5 True
<= Minore o uguale a 4 <= 9 True
Esempi pratici di confronto
eta = 18
maggiorenne = eta >= 18
print(maggiorenne)  # True

temperatura = 25
fa_freddo = temperatura < 15
print(fa_freddo)  # False

password = "python123"
password_corretta = password == "python123"
print(password_corretta)  # True

# Confronto tra stringhe (alfabetico)
print("apple" < "banana")  # True
print("Python" == "python")  # False (case-sensitive!)
⚠️ Errore comune: = vs ==

Uno degli errori più frequenti per i principianti:

  • = è l'operatore di assegnazione (assegna un valore a una variabile)
  • == è l'operatore di confronto (verifica se due valori sono uguali)
x = 5      # Assegnazione: x ora vale 5
x == 5     # Confronto: verifica se x è uguale a 5 (restituisce True)

2. Operatori logici

Gli operatori logici permettono di combinare più condizioni per creare espressioni più complesse. Python fornisce tre operatori logici fondamentali:

Operatore Significato Quando è True Esempio
and E logico Quando ENTRAMBE le condizioni sono vere True and TrueTrue
or O logico Quando ALMENO UNA condizione è vera True or FalseTrue
not Negazione Inverte il valore di verità not FalseTrue

Tabelle di verità

Operatore AND

True and True   → True
True and False  → False
False and True  → False
False and False → False

Operatore OR

True or True    → True
True or False   → True
False or True   → True
False or False  → False
Esempi pratici con operatori logici
# Verificare range di età
eta = 25
maggiorenne = eta >= 18 and eta < 65
print(f"Adulto lavoratore: {maggiorenne}")  # True

# Verificare condizioni meteo per uscire
temperatura = 22
piove = False
si_esce = temperatura > 15 and not piove
print(f"Possiamo uscire: {si_esce}")  # True

# Verificare giorno weekend
giorno = "sabato"
e_weekend = giorno == "sabato" or giorno == "domenica"
print(f"È weekend: {e_weekend}")  # True

# Condizione complessa per sconto
importo = 120
cliente_premium = True
ha_sconto = importo > 100 or cliente_premium
print(f"Ha diritto allo sconto: {ha_sconto}")  # True
🔑 Precedenza degli operatori logici

Gli operatori logici hanno un ordine di precedenza:

  1. not (più alta precedenza)
  2. and
  3. or (più bassa precedenza)

Usa le parentesi per rendere chiaro l'ordine di valutazione:

# Senza parentesi (può creare confusione)
risultato = True or False and False  # True

# Con parentesi (chiaro e leggibile)
risultato = True or (False and False)  # True
risultato = (True or False) and False  # False

3. Strutture condizionali: if, elif, else

L'istruzione if permette al programma di eseguire un blocco di codice solo se una condizione è vera. È il cuore del processo decisionale in Python.

Sintassi base:

if condizione:
    # codice da eseguire se la condizione è vera
    istruzione1
    istruzione2
⚠️ CRITICO: L'indentazione in Python

Python usa l'indentazione (spazi o tab all'inizio della riga) per definire i blocchi di codice. Questo è OBBLIGATORIO, non è una questione di stile!

  • Usa 4 spazi (standard) o 1 tab per l'indentazione
  • Tutti gli statement nello stesso blocco devono avere la stessa indentazione
  • NON mischiare spazi e tab
  • Dopo if, elif, else, while, for ci vuole sempre i due punti :

3.1 If semplice

# Esempio base
eta = 20

if eta >= 18:
    print("Sei maggiorenne")
    print("Puoi votare")

print("Questo viene eseguito sempre")  # Fuori dal blocco if

Diagramma di flusso If

Inizio
⬇️
Valuta condizione
⬇️
✓ True
⬇️
Esegui blocco if
✗ False
⬇️
Salta blocco if
⬇️
Continua esecuzione

3.2 If-Else: due alternative

L'istruzione else permette di specificare un blocco di codice da eseguire quando la condizione dell'if è falsa.

Sintassi if-else:

if condizione:
    # codice se condizione vera
else:
    # codice se condizione falsa
# Esempio pratico
temperatura = 25

if temperatura > 30:
    print("Fa molto caldo! 🥵")
    print("Meglio restare all'ombra")
else:
    print("La temperatura è gradevole 😊")
    print("Possiamo uscire tranquillamente")

print("Buona giornata!")  # Eseguito sempre
Esempio: Verifica password
password_corretta = "python2024"
tentativo = input("Inserisci la password: ")

if tentativo == password_corretta:
    print("✅ Accesso consentito!")
    print("Benvenuto nel sistema")
else:
    print("❌ Password errata!")
    print("Accesso negato")

3.3 If-Elif-Else: scelte multiple

elif (abbreviazione di "else if") permette di verificare condizioni multiple in sequenza. Python valuta le condizioni dall'alto verso il basso e esegue il primo blocco la cui condizione è vera.

Sintassi if-elif-else:

if condizione1:
    # codice se condizione1 vera
elif condizione2:
    # codice se condizione2 vera
elif condizione3:
    # codice se condizione3 vera
else:
    # codice se nessuna condizione vera
📘 Caratteristiche di elif
  • Puoi avere quanti elif vuoi
  • L'else finale è opzionale
  • Solo IL PRIMO blocco con condizione vera viene eseguito, gli altri vengono saltati
  • L'ordine delle condizioni è importante!
Esempio: Valutazione voto
voto = int(input("Inserisci il voto (0-30): "))

if voto < 0 or voto > 30:
    print("⚠️ Voto non valido!")
elif voto < 18:
    print("❌ Insufficiente")
    print("Devi ripetere l'esame")
elif voto < 24:
    print("✅ Sufficiente")
    print("Hai passato l'esame")
elif voto < 27:
    print("✅ Buono")
    print("Complimenti!")
elif voto < 30:
    print("✅ Ottimo")
    print("Eccellente risultato!")
else:  # voto == 30
    print("🌟 Trenta e lode!")
    print("Risultato straordinario!")

print("\nFine valutazione")

Output con voto 28:

Inserisci il voto (0-30): 28
✅ Ottimo
Eccellente risultato!

Fine valutazione

3.4 If annidati

È possibile inserire strutture if all'interno di altre strutture if. Questo si chiama annidamento (nesting).

# Verifica accesso con età e documento
eta = int(input("Quanti anni hai? "))

if eta >= 18:
    print("Età verificata ✓")
    
    ha_documento = input("Hai un documento? (si/no): ")
    
    if ha_documento.lower() == "si":
        print("✅ Accesso consentito")
        print("Benvenuto!")
    else:
        print("❌ Serve un documento di identità")
else:
    print("❌ Devi essere maggiorenne")
⚠️ Attenzione all'indentazione negli if annidati

Ogni livello di annidamento richiede un ulteriore livello di indentazione. Mantieni il codice leggibile evitando troppi livelli di annidamento (massimo 3-4).

if condizione1:
if condizione2:
if condizione3:
print("Troppi livelli! 😵")

4. Ciclo While: ripetizione condizionale

Il ciclo while ripete un blocco di codice finché una condizione rimane vera. È utile quando non sai in anticipo quante volte dovrai ripetere l'operazione.

Sintassi while:

while condizione:
    # codice da ripetere
    # ricordati di modificare la condizione!

Diagramma di flusso While

Inizio
⬇️
Valuta condizione
⬇️
✓ True
⬇️
Esegui blocco
⬇️
↻ Torna alla condizione
✗ False
⬇️
Esci dal ciclo
Esempio base: Contatore
contatore = 1

while contatore <= 5:
    print(f"Iterazione numero {contatore}")
    contatore += 1  # IMPORTANTE: aggiorna la variabile!

print("Ciclo terminato")

# Output:
# Iterazione numero 1
# Iterazione numero 2
# Iterazione numero 3
# Iterazione numero 4
# Iterazione numero 5
# Ciclo terminato
🚨 PERICOLO: Cicli infiniti

Se la condizione del while rimane sempre vera, il ciclo non terminerà mai! Questo è chiamato ciclo infinito e bloccherà il programma.

# SBAGLIATO - Ciclo infinito!
contatore = 1
while contatore <= 5:
    print(contatore)
    # Manca contatore += 1, quindi contatore rimane sempre 1!

# CORRETTO
contatore = 1
while contatore <= 5:
    print(contatore)
    contatore += 1  # ✓ Aggiorna la variabile

Se il tuo programma si blocca, premi Ctrl + C per interromperlo.

Esempio pratico: Gioco indovina numero
import random

numero_segreto = random.randint(1, 10)
tentativi = 0
max_tentativi = 5

print("🎮 Indovina il numero tra 1 e 10!")
print(f"Hai {max_tentativi} tentativi disponibili\n")

while tentativi < max_tentativi:
    tentativo = int(input("Il tuo numero: "))
    tentativi += 1
    
    if tentativo == numero_segreto:
        print(f"🎉 Hai vinto in {tentativi} tentativi!")
        break  # Esce dal ciclo
    elif tentativo < numero_segreto:
        print("📈 Troppo basso!")
    else:
        print("📉 Troppo alto!")
    
    print(f"Tentativi rimasti: {max_tentativi - tentativi}\n")
else:
    print(f"😢 Hai esaurito i tentativi! Il numero era {numero_segreto}")

While con condizioni complesse

# Input validation: chiedi finché non inseriscono un valore valido
eta = -1

while eta < 0 or eta > 120:
    eta = int(input("Inserisci la tua età (0-120): "))
    
    if eta < 0 or eta > 120:
        print("⚠️ Età non valida! Riprova.\n")

print(f"✅ Età registrata: {eta} anni")

5. Ciclo For: iterazione su sequenze

Il ciclo for itera su una sequenza di elementi (lista, stringa, range, ecc.). È più pulito e sicuro del while quando sai in anticipo su cosa devi iterare.

Sintassi for:

for variabile in sequenza:
    # codice da ripetere
    # variabile assume ogni valore della sequenza

5.1 For con range()

La funzione range() genera una sequenza di numeri. È lo strumento più comune usato con i cicli for.

Sintassi Descrizione Esempio
range(stop) Da 0 a stop-1 range(5) → 0, 1, 2, 3, 4
range(start, stop) Da start a stop-1 range(2, 7) → 2, 3, 4, 5, 6
range(start, stop, step) Da start a stop-1, con incremento step range(0, 10, 2) → 0, 2, 4, 6, 8
Esempi con range()
# Stampare numeri da 0 a 4
for i in range(5):
    print(i)
# Output: 0 1 2 3 4

# Stampare numeri da 1 a 5
for i in range(1, 6):
    print(i)
# Output: 1 2 3 4 5

# Stampare numeri pari da 0 a 10
for i in range(0, 11, 2):
    print(i)
# Output: 0 2 4 6 8 10

# Contare all'indietro
for i in range(10, 0, -1):
    print(i)
# Output: 10 9 8 7 6 5 4 3 2 1
📘 Nota importante su range()

Il valore finale (stop) NON è incluso nella sequenza. range(1, 5) genera: 1, 2, 3, 4 (il 5 non c'è!).

5.2 For con stringhe

Puoi iterare direttamente sui caratteri di una stringa:

parola = "Python"

for lettera in parola:
    print(lettera)

# Output:
# P
# y
# t
# h
# o
# n
Contare vocali in una stringa
testo = input("Inserisci una frase: ")
vocali = "aeiouAEIOU"
contatore_vocali = 0

for carattere in testo:
    if carattere in vocali:
        contatore_vocali += 1

print(f"La frase contiene {contatore_vocali} vocali")

5.3 For con liste

Le liste sono collezioni ordinate di elementi. Il for è perfetto per iterarle:

frutti = ["mela", "banana", "arancia", "pera"]

for frutto in frutti:
    print(f"Mi piace {frutto}")

# Output:
# Mi piace mela
# Mi piace banana
# Mi piace arancia
# Mi piace pera
Calcolare la somma di una lista
numeri = [10, 25, 30, 15, 20]
somma = 0

for numero in numeri:
    somma += numero

print(f"La somma totale è: {somma}")  # 100

# In alternativa, Python ha una funzione built-in:
print(f"Somma con sum(): {sum(numeri)}")  # 100

5.4 For con enumerate()

Se hai bisogno sia dell'elemento che del suo indice, usa enumerate():

studenti = ["Marco", "Laura", "Giovanni", "Sara"]

for indice, studente in enumerate(studenti):
    print(f"{indice + 1}. {studente}")

# Output:
# 1. Marco
# 2. Laura
# 3. Giovanni
# 4. Sara

6. Controllo dei cicli: break, continue, pass

Python fornisce parole chiave speciali per controllare il flusso all'interno dei cicli.

6.1 Break: uscire dal ciclo

break interrompe immediatamente il ciclo, anche se la condizione è ancora vera o ci sono ancora elementi da iterare.

# Cercare un elemento specifico
numeri = [10, 20, 30, 40, 50]
target = 30

for numero in numeri:
    if numero == target:
        print(f"✅ Trovato {target}!")
        break  # Esce dal ciclo
    print(f"Controllo {numero}...")
else:
    # Questo else si esegue solo se il ciclo NON è stato interrotto da break
    print("❌ Numero non trovato")

# Output:
# Controllo 10...
# Controllo 20...
# ✅ Trovato 30!
Password con tentativi limitati
password_corretta = "python2024"
max_tentativi = 3

for tentativo in range(1, max_tentativi + 1):
    password = input(f"Tentativo {tentativo}/{max_tentativi} - Password: ")
    
    if password == password_corretta:
        print("✅ Accesso consentito!")
        break
    else:
        print("❌ Password errata")
else:
    print("🔒 Account bloccato per troppi tentativi falliti")

6.2 Continue: saltare all'iterazione successiva

continue salta il resto del codice nell'iterazione corrente e passa direttamente alla successiva.

# Stampare solo numeri pari
for numero in range(1, 11):
    if numero % 2 != 0:  # Se è dispari
        continue  # Salta il resto e vai al prossimo
    
    print(numero)

# Output: 2 4 6 8 10
Filtrare valori non validi
voti = [28, 30, -1, 25, 0, 22, 18, -5, 27]

print("Voti validi:")
for voto in voti:
    if voto < 18 or voto > 30:
        continue  # Salta i voti non validi
    
    print(f"✓ {voto}")

# Output:
# Voti validi:
# ✓ 28
# ✓ 30
# ✓ 25
# ✓ 22
# ✓ 18
# ✓ 27

6.3 Pass: segnaposto vuoto

pass è un'operazione nulla. Non fa niente, ma è utile come segnaposto quando la sintassi richiede un blocco di codice ma non hai ancora deciso cosa scrivere.

# Struttura da implementare dopo
for i in range(10):
    if i % 2 == 0:
        pass  # TODO: implementare logica per numeri pari
    else:
        print(f"{i} è dispari")

# Funzione ancora da scrivere
def funzione_futura():
    pass  # Verrà implementata dopo

# Pass in if per chiarezza
eta = 25
if eta >= 18:
    pass  # Nessuna azione particolare
else:
    print("Minorenne")

7. Cicli annidati

È possibile inserire cicli all'interno di altri cicli. Ogni iterazione del ciclo esterno esegue TUTTE le iterazioni del ciclo interno.

# Esempio base: tabella moltiplicazione
for i in range(1, 4):  # Ciclo esterno: 3 iterazioni
    for j in range(1, 4):  # Ciclo interno: 3 iterazioni per ogni i
        print(f"{i} x {j} = {i * j}")
    print()  # Riga vuota dopo ogni serie

# Output:
# 1 x 1 = 1
# 1 x 2 = 2
# 1 x 3 = 3
#
# 2 x 1 = 2
# 2 x 2 = 4
# 2 x 3 = 6
# ...
Disegnare pattern con asterischi
# Triangolo rettangolo
altezza = 5

for riga in range(1, altezza + 1):
    for colonna in range(riga):
        print("*", end="")
    print()  # Va a capo

# Output:
# *
# **
# ***
# ****
# *****

print("\n" + "="*20 + "\n")

# Quadrato pieno
lato = 4

for riga in range(lato):
    for colonna in range(lato):
        print("■", end=" ")
    print()

# Output:
# ■ ■ ■ ■
# ■ ■ ■ ■
# ■ ■ ■ ■
# ■ ■ ■ ■
⚠️ Attenzione alle performance

I cicli annidati possono diventare molto lenti se iterano su grandi quantità di dati. Un ciclo con 1000 elementi contenente un altro ciclo con 1000 elementi eseguirà 1.000.000 di operazioni!

8. While vs For: quando usare quale?

Usa WHILE quando:

  • Non sai quante iterazioni servono
  • La condizione di uscita dipende da eventi esterni (input utente, sensori, ecc.)
  • Vuoi continuare finché qualcosa accade
# Esempio: input validation
risposta = ""
while risposta != "si" and risposta != "no":
    risposta = input("Risposta (si/no): ").lower()

Usa FOR quando:

  • Sai quante iterazioni servono
  • Devi iterare su una collezione (lista, stringa, range)
  • Vuoi scorrere elementi uno per uno
# Esempio: elaborare dati
voti = [28, 30, 25, 27]
for voto in voti:
    print(f"Voto: {voto}")

9. Programmi completi di esempio

Calcolatrice con menu
print("=" * 40)
print("CALCOLATRICE")
print("=" * 40)

continua = True

while continua:
    print("\nOperazioni disponibili:")
    print("1. Addizione (+)")
    print("2. Sottrazione (-)")
    print("3. Moltiplicazione (*)")
    print("4. Divisione (/)")
    print("5. Esci")
    
    scelta = input("\nScegli operazione (1-5): ")
    
    if scelta == "5":
        print("👋 Arrivederci!")
        break
    
    if scelta not in ["1", "2", "3", "4"]:
        print("⚠️ Scelta non valida!")
        continue
    
    # Input numeri
    num1 = float(input("Primo numero: "))
    num2 = float(input("Secondo numero: "))
    
    # Calcolo
    if scelta == "1":
        risultato = num1 + num2
        operazione = "+"
    elif scelta == "2":
        risultato = num1 - num2
        operazione = "-"
    elif scelta == "3":
        risultato = num1 * num2
        operazione = "*"
    else:  # scelta == "4"
        if num2 == 0:
            print("❌ Errore: divisione per zero!")
            continue
        risultato = num1 / num2
        operazione = "/"
    
    print(f"\n✅ Risultato: {num1} {operazione} {num2} = {risultato}")
    
    altra = input("\nAltra operazione? (si/no): ").lower()
    if altra != "si":
        continua = False
        print("👋 Arrivederci!")

print("\nProgramma terminato")
Analizzatore di testo
print("📝 ANALIZZATORE DI TESTO\n")

testo = input("Inserisci un testo: ")

# Contatori
caratteri = len(testo)
parole = len(testo.split())
vocali_count = 0
consonanti_count = 0
numeri_count = 0
spazi_count = 0

# Analisi carattere per carattere
for carattere in testo:
    if carattere.isalpha():  # È una lettera?
        if carattere.lower() in "aeiou":
            vocali_count += 1
        else:
            consonanti_count += 1
    elif carattere.isdigit():  # È un numero?
        numeri_count += 1
    elif carattere == " ":
        spazi_count += 1

# Risultati
print("\n" + "=" * 40)
print("RISULTATI ANALISI")
print("=" * 40)
print(f"Caratteri totali: {caratteri}")
print(f"Parole: {parole}")
print(f"Vocali: {vocali_count}")
print(f"Consonanti: {consonanti_count}")
print(f"Numeri: {numeri_count}")
print(f"Spazi: {spazi_count}")

# Lettere più frequenti
print("\nLettere più frequenti:")
for lettera in "aeiou":
    count = testo.lower().count(lettera)
    if count > 0:
        print(f"  {lettera}: {count} volte")
🎯 Quiz di Autovalutazione

1. Cosa stampa questo codice?

x = 10
if x > 5:
    if x < 15:
        print("A")
    else:
        print("B")
else:
    print("C")
  • a) A ✅
  • b) B
  • c) C
  • d) Niente

2. Quante volte viene stampato "Ciao"?

for i in range(3):
    for j in range(2):
        print("Ciao")
  • a) 2
  • b) 3
  • c) 5
  • d) 6 ✅

3. Cosa fa questo codice?

for i in range(5):
    if i == 3:
        break
    print(i)
  • a) Stampa: 0 1 2 3 4
  • b) Stampa: 0 1 2 ✅
  • c) Stampa: 0 1 2 3
  • d) Errore

4. Qual è il risultato di: range(2, 8, 2)?

  • a) 2, 4, 6, 8
  • b) 2, 4, 6 ✅
  • c) 0, 2, 4, 6, 8
  • d) 2, 3, 4, 5, 6, 7

5. Cosa stampa questo codice?

x = 0
while x < 3:
    x += 1
    if x == 2:
        continue
    print(x)
  • a) 1 2 3
  • b) 1 3 ✅
  • c) 0 1 2
  • d) 2 3

10. Esercizi pratici

🎓 Esercizi per consolidare le conoscenze

Esercizio 1 - Base: Scrivi un programma che chieda un numero e stampi se è pari o dispari.

Esercizio 2 - Base: Crea un programma che stampi tutti i numeri da 1 a 20, ma sostituisci i multipli di 3 con "Fizz" e i multipli di 5 con "Buzz".

Esercizio 3 - Medio: Scrivi un programma che calcoli il fattoriale di un numero (n! = 1 × 2 × 3 × ... × n).

Esercizio 4 - Medio: Crea un programma che verifichi se una parola è un palindromo (si legge uguale da destra e da sinistra, es: "anna", "radar").

Esercizio 5 - Avanzato: Implementa il gioco "Carta, Forbice, Sasso" contro il computer con conteggio dei punti.

Esercizio 6 - Avanzato: Scrivi un programma che stampi la sequenza di Fibonacci fino a un certo numero di termini inserito dall'utente (0, 1, 1, 2, 3, 5, 8, 13, ...).

Esercizio 7 - Sfida: Crea un programma che simuli un bancomat: permetti di depositare, prelevare, controllare il saldo e uscire. Usa un menu con ciclo while.

11. Best Practices

✅ Consigli per scrivere buone strutture di controllo:
  • Usa for invece di while quando possibile: È più sicuro e leggibile
  • Evita cicli infiniti: Assicurati sempre che la condizione possa diventare falsa
  • Non annidare troppo: Massimo 3-4 livelli, altrimenti spezza in funzioni
  • Usa break e continue con parsimonia: Troppi rendono il codice difficile da seguire
  • Commenta la logica complessa: Spiega perché, non cosa
  • Nomi variabili descrittivi: età_utente è meglio di x
  • Mantieni l'indentazione consistente: Usa sempre 4 spazi
📚 Prossimi passi:

Ora che conosci le strutture di controllo, sei pronto per:

  • Strutture dati avanzate (liste, tuple, dizionari, set)
  • Definire funzioni personalizzate
  • Gestire file e dati
  • Lavorare con moduli e librerie esterne
  • Gestione degli errori (try-except)